﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "InplaceEditProjectStyleMaterialMap.h"
#include "InplaceEditSharedContent.h"

// 平台头文件
#include "DbObjectUtils.h"
#include "IElementParentReporter.h"
#include "IElementBasicInformation.h"
#include "IDocument.h"
#include "IGenericElement.h"
#include "IElementModelShape.h"
#include "IGraphicsElementShape.h"
#include "IGraphicsElementShapeReference.h"
#include "IElementViewSpecificShapeComponent.h"
#include "ElementUtils.h"
#include "IGraphicsStyle.h"
#include "IGraphicsMaterial.h"
#include "IFillPattern.h"
#include "ILineTypeNew.h"
#include "NdbUpgrade.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;


BEGIN_UPGRADE_CLASS(gcmp, InplaceEditProjectStyleMaterialMap, 2)
ADD_MAP_PROPERTY(Int64, ElementId, FillPatternMap)
ADD_MAP_PROPERTY(Int64, ElementId, LineTypeNewMap)
END_UPGRADE_CLASS

DBOBJECT_DATA_DEFINE(InplaceEditProjectStyleMaterialMap)
{
    m_pOwnerElement = nullptr;
}

const InplaceEditProjectStyleMaterialMap *InplaceEditProjectStyleMaterialMap::Get(IDocument *pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"参数为空",L"GDMPLab",L"2024-03-30");
    const IGenericElement *pGenericElement = quick_cast<IGenericElement>(
        pDoc->GetUniqueElementByClassUid(InplaceEditProjectStyleMaterialMap::GetClassId().GetGuid()));
    if (pGenericElement && pGenericElement->GetExternalObject())
    {
        return quick_cast<const InplaceEditProjectStyleMaterialMap>(pGenericElement->GetExternalObject());
    }

    return nullptr;
}

InplaceEditProjectStyleMaterialMap *InplaceEditProjectStyleMaterialMap::GetFw(IDocument *pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"参数为空",L"GDMPLab",L"2024-03-30");
    IGenericElement *pGenericElement = quick_cast<IGenericElement>(
        pDoc->GetUniqueElementByClassUid(InplaceEditProjectStyleMaterialMap::GetClassId().GetGuid()));
    if (pGenericElement && pGenericElement->GetExternalObject())
    {
        return quick_cast<InplaceEditProjectStyleMaterialMap>(pGenericElement->GetExternalObject());
    }

    return nullptr;
}

InplaceEditProjectStyleMaterialMap* gcmp::InplaceEditProjectStyleMaterialMap::Create(IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"输入参数为空",L"GDMPLab",L"2024-03-30");

    OwnerPtr<InplaceEditProjectStyleMaterialMap> opKeyFrameIdMgr = NEW_AS_OWNER_PTR(InplaceEditProjectStyleMaterialMap);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opKeyFrameIdMgr, L"opKeyFrameIdMgr为空",L"GDMPLab",L"2024-03-30");

    IGenericElement* pGenericElement = IGenericElement::Create(
        pDoc, TransferOwnership(opKeyFrameIdMgr), InplaceEditProjectStyleMaterialMap::GetClassId().GetGuid()
        , ElementCreationOptions::Normal);

    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement, L"pGenericElement为空",L"GDMPLab",L"2024-03-30");
    ElementUtils::MakeElementUnique(pGenericElement, InplaceEditProjectStyleMaterialMap::GetClassId().GetGuid());

    return quick_cast<InplaceEditProjectStyleMaterialMap>(pGenericElement->GetExternalObject());
}

ElementId gcmp::InplaceEditProjectStyleMaterialMap::GetFamilyStyleId(ElementId projectStyleId) const
{
    auto iter = GetStyleMap__().find(projectStyleId.AsInt64());
    if (iter != GetStyleMap__().end())
    {
        return iter->second;
    }

    return ElementId::InvalidID;
}

ElementId gcmp::InplaceEditProjectStyleMaterialMap::GetFamilyMaterialId(ElementId projectMaterialId) const
{
    auto iter = GetMaterialMap__().find(projectMaterialId.AsInt64());
    if (iter != GetMaterialMap__().end())
    {
        return iter->second;
    }

    return ElementId::InvalidID;
}

ElementId gcmp::InplaceEditProjectStyleMaterialMap::GetFamilyFillPatternId(ElementId projectGenericId) const
{
    auto iter = GetFillPatternMap__().find(projectGenericId.AsInt64());
    if (iter != GetFillPatternMap__().end())
    {
        return iter->second;
    }

    return ElementId::InvalidID;
}

ElementId gcmp::InplaceEditProjectStyleMaterialMap::GetFamilyLineTypeNewId(ElementId projectGenericId) const
{
    auto iter = GetLineTypeNewMap__().find(projectGenericId.AsInt64());
    if (iter != GetLineTypeNewMap__().end())
    {
        return iter->second;
    }

    return ElementId::InvalidID;
}

bool gcmp::InplaceEditProjectStyleMaterialMap::AddProjectStyle(ElementId projectStyleId, const IGraphicsStyleData* pStyleData)
{
    // 样式已存在，则不需要创建
    auto iter = GetStyleMap__().find(projectStyleId.AsInt64());
    if (iter != GetStyleMap__().end())
    {
        return false;
    }

    // 样式不存在，需要创建对应的样式对象
    IGraphicsStyle* pStyle = IGraphicsStyle::Create(GetDocument(), ElementCreationOptions::Normal);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pStyle, L"样式创建失败",L"GDMPLab",L"2024-03-30");
    pStyle->SetGraphicsStyleData(*pStyleData);
    GetStyleMapFW__()[projectStyleId.AsInt64()] = pStyle->GetElementId();

    return true;
}

bool gcmp::InplaceEditProjectStyleMaterialMap::AddProjectMaterial(ElementId projectMaterialId, const IGraphicsMaterialData* pMaterialData)
{
    // 材质已存在，则不需要创建
    auto iter = GetMaterialMap__().find(projectMaterialId.AsInt64());
    if (iter != GetMaterialMap__().end())
    {
        return false;
    }

    // 材质不存在，需要创建对应的材质对象
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pMaterialData, L"pMaterialData为空",L"GDMPLab",L"2024-03-30");
    std::wstring materialName = L"项目材质"+StringUtil::ToWString(projectMaterialId.AsInt64());
    IGraphicsMaterial* pMaterial = IGraphicsMaterial::Create(GetDocument(), ElementCreationOptions::Normal, materialName);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pMaterial, L"材质创建失败",L"GDMPLab",L"2024-03-30");
    pMaterial->UpdateMaterialInstanceByGraphicsMaterialData(*pMaterialData);
    GetMaterialMapFW__()[projectMaterialId.AsInt64()] = pMaterial->GetElementId();

    return true;
}

bool gcmp::InplaceEditProjectStyleMaterialMap::AddProjectFillPattern(ElementId projectGenericId, const IFillPatternData * pFillPatternData)
{
    // 填充样式已存在，则不需要创建
    auto iter = GetFillPatternMap__().find(projectGenericId.AsInt64());
    if (iter != GetFillPatternMap__().end())
    {
        return false;
    }

    // 填充样式不存在，需要创建对应的填充样式对象
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFillPatternData, L"pFillPatternData为空",L"GDMPLab",L"2024-03-30");
    IFillPattern* pFillPattern = IFillPattern::Create(GetDocument(),pFillPatternData->Clone(), false);
    
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pFillPattern, L"填充样式创建失败",L"GDMPLab",L"2024-03-30");
    GetFillPatternMapFW__()[projectGenericId.AsInt64()] = pFillPattern->GetOwnerElement()->GetElementId();

    return true;
}

bool gcmp::InplaceEditProjectStyleMaterialMap::AddProjectLineTypeNew(ElementId projectGenericId, const ILineTypeData * pLineTypeData)
{
    //线型已存在，则不需要创建
    auto iter = GetLineTypeNewMap__().find(projectGenericId.AsInt64());
    if (iter != GetLineTypeNewMap__().end())
    {
        return false;
    }

    //线型不存在，需要创建对应的线型对象
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pLineTypeData, L"pLineTypeData为空",L"GDMPLab",L"2024-03-30");
    ILineTypeNew* pLineTypeNew = ILineTypeNew::Create(GetDocument(), pLineTypeData->Clone(), false);

    DBG_WARN_AND_RETURN_FALSE_UNLESS(pLineTypeNew, L"线型创建失败",L"GDMPLab",L"2024-03-30");
    GetLineTypeNewMapFW__()[projectGenericId.AsInt64()] = pLineTypeNew->GetOwnerElement()->GetElementId();

    return true;
}

IDocument *InplaceEditProjectStyleMaterialMap::GetDocument() const
{
    if (!m_pOwnerElement)
    {
        return nullptr;
    }
    return m_pOwnerElement->GetDocument();
}

ElementId InplaceEditProjectStyleMaterialMap::GetOwnerElementId() const
{
    if (!m_pOwnerElement)
    {
        return ElementId::InvalidID;
    }
    return m_pOwnerElement->GetElementId();
}


#pragma region IExternalObject接口
NdbObject* InplaceEditProjectStyleMaterialMap::GetTopOwnerObject() const
{
    return quick_cast<NdbObject>(const_cast<IElement*>(GetOwnerElement()));
}

#pragma region 关联更新

void InplaceEditProjectStyleMaterialMap::UpdateForWeakParentDeletion(const std::set<ElementId>& deletedElementIds)
{
}

void InplaceEditProjectStyleMaterialMap::ReportParents(IElementParentReporter& reporter) const
{
    const IElement* pElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"IElement为空",L"GDMPLab",L"2024-03-30");

    const IElementModelShape *pModelShape = m_pOwnerElement->GetElementModelShape();
    if (pModelShape && pModelShape->GetGraphicsElementShape())
    {
        std::vector<ElementId> refIds;
        pModelShape->GetGraphicsElementShape()->GetReferencedElementIds(refIds);
        reporter.ReportWeak(refIds);
    }

    FOR_EACH(item, GetStyleMap__())
    {
        reporter.ReportWeak(item.second);
    }
    FOR_EACH(item, GetMaterialMap__())
    {
        reporter.ReportWeak(item.second);
    }
    FOR_EACH(item, GetFillPatternMap__())
    {
        reporter.ReportWeak(item.second);
    }
    FOR_EACH(item, GetLineTypeNewMap__())
    {
        reporter.ReportWeak(item.second);
    }
}

#pragma endregion 关联更新

#pragma region 其他
bool InplaceEditProjectStyleMaterialMap::FinishEditing()
{
    return true;
}
#pragma endregion 其他

#pragma region protected

bool InplaceEditProjectStyleMaterialMap::SetOwnerElement(IElement* pOwnerElement)
{
    m_pOwnerElement = pOwnerElement;
    return true;
}

#pragma endregion protected
#pragma endregion IExternalObject接口
